﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;
using ArchPostprocessing.CompoundStructureManage.DataDefinition;
using ArchPostprocessing.CompoundStructureManage.Forms;
using Autodesk.Revit.ApplicationServices;
using Autodesk.Revit.DB;
using Autodesk.Revit.UI;

namespace ArchPostprocessing.CompoundStructureManage.Managers.Controllers
{
	public class WallSplitController
	{
		public WallSplitController(ExternalCommandData cmdData)
		{
			this.m_ComdData = cmdData;
			this.m_UIApp = cmdData.Application;
			this.m_UIDoc = this.m_UIApp.ActiveUIDocument;
			this.m_App = this.m_UIApp.Application;
			this.m_Doc = this.m_UIDoc.Document;
		}

		public void SplitWalls(List<Wall> selWalls)
		{
			List<WallType> list = new List<WallType>();
			using (List<Wall>.Enumerator enumerator = selWalls.GetEnumerator())
			{
				while (enumerator.MoveNext())
				{
					Wall wall = enumerator.Current;
					if (list.FindIndex((WallType item) => item.Id.IntegerValue == wall.WallType.Id.IntegerValue) == -1)
					{
						list.Add(wall.WallType);
					}
				}
			}
			WallTypeSplitForm wallTypeSplitForm = new WallTypeSplitForm(list, this.m_Doc);
			if (wallTypeSplitForm.ShowDialog() != DialogResult.OK)
			{
				return;
			}
			Transaction transaction = new Transaction(this.m_Doc);
			try
			{
				transaction.Start("split wall");
				List<Wall> list2 = new List<Wall>();
				foreach (Wall wall3 in selWalls)
				{
					List<WallTypeLayerInfos> userNewTypeByWallType = wallTypeSplitForm.GetUserNewTypeByWallType(wall3.WallType);
					if (wall3.Flipped)
					{
						userNewTypeByWallType.Reverse();
					}
					WallUtils.DisallowWallJoinAtEnd(wall3, 0);
					WallUtils.DisallowWallJoinAtEnd(wall3, 1);
					double num = 0.0;
					for (int i = 0; i < userNewTypeByWallType.Count; i++)
					{
						WallTypeLayerInfos wallTypeLayerInfos = userNewTypeByWallType[i];
						try
						{
							this.SpliteWallLayer(wall3, wallTypeLayerInfos, num, ref list2);
							num += wallTypeLayerInfos.Width;
						}
						catch (Exception)
						{
							num += wallTypeLayerInfos.Width;
						}
					}
					this.m_Doc.Delete(wall3.Id);
				}
				foreach (Wall wall2 in list2)
				{
					WallUtils.AllowWallJoinAtEnd(wall2, 0);
					WallUtils.AllowWallJoinAtEnd(wall2, 1);
				}
				this.JoinWalls(ref list2);
				transaction.Commit();
			}
			catch (Exception ex)
			{
				string message = ex.Message;
				if (transaction != null)
				{
					transaction.RollBack();
				}
			}
		}

		private void JoinWalls(ref List<Wall> splitedWalls)
		{
			if (splitedWalls.Count < 2)
			{
				return;
			}
			for (int i = 1; i < splitedWalls.Count; i++)
			{
				try
				{
					JoinGeometryUtils.JoinGeometry(this.m_Doc, splitedWalls[i - 1], splitedWalls[i]);
				}
				catch (Exception)
				{
				}
			}
		}

		private void SpliteWallLayer(Wall wall, WallTypeLayerInfos typeLayerInfos, double offset, ref List<Wall> splitedWalls)
		{
			Curve curve = (wall.Location as LocationCurve).Curve;
			XYZ orientation = wall.Orientation;
			ICollection<ElementId> source = new List<ElementId>();
			try
			{
				source = ElementTransformUtils.CopyElement(this.m_Doc, wall.Id, XYZ.Zero);
			}
			catch (Exception ex)
			{
				string message = ex.Message;
				return;
			}
			Wall wall2 = this.m_Doc.GetElement(source.ElementAt(0)) as Wall;
			string typeName = typeLayerInfos.TypeName;
			List<CompoundStructureLayer> list = new List<CompoundStructureLayer>();
			List<WallLayerInfos> layerList = typeLayerInfos.LayerList;
			if (wall.Flipped)
			{
				layerList.Reverse();
			}
			foreach (WallLayerInfos wallLayerInfos in layerList)
			{
				list.Add(wallLayerInfos.StructureLayer);
			}
			WallType wallType = WallTypeManager.GetWallType(typeName, wall.WallType, list, this.m_Doc, false);
			if (wallType == null)
			{
				this.m_Doc.Delete(wall2.Id);
				return;
			}
			wall2.WallType = wallType;
			if (!typeLayerInfos.HasStructureLayer())
			{
				this.DeleteWindowAndDoorWithWall(wall2);
			}
			double offsetSpace = wall.Width / 2.0 - offset - typeLayerInfos.Width / 2.0;
			(wall2.Location as LocationCurve).Curve = WallCommon.GetOffsetWallLocation(curve, orientation, offsetSpace);
			splitedWalls.Add(wall2);
		}

		private void DeleteWindowAndDoorWithWall(Wall wall)
		{
			FilteredElementCollector filteredElementCollector = new FilteredElementCollector(this.m_Doc, this.m_Doc.ActiveView.Id);
			List<ElementId> list = new List<ElementId>();
			foreach (Element element in filteredElementCollector.OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Doors).ToElements())
			{
				FamilyInstance familyInstance = element as FamilyInstance;
				if (familyInstance.Host != null && familyInstance.Host.Id.IntegerValue == wall.Id.IntegerValue)
				{
					list.Add(element.Id);
				}
			}
			foreach (Element element2 in new FilteredElementCollector(this.m_Doc, this.m_Doc.ActiveView.Id).OfClass(typeof(FamilyInstance)).OfCategory(BuiltInCategory.OST_Windows).ToElements())
			{
				FamilyInstance familyInstance2 = element2 as FamilyInstance;
				if (familyInstance2.Host != null && familyInstance2.Host.Id.IntegerValue == wall.Id.IntegerValue)
				{
					list.Add(element2.Id);
				}
			}
			this.m_Doc.Delete(list);
		}

		private ExternalCommandData m_ComdData;

		private UIApplication m_UIApp;

		private UIDocument m_UIDoc;

        private Autodesk.Revit.ApplicationServices.Application m_App;

		private Document m_Doc;
	}
}
